{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "rQc-wXjqrEuR"
   },
   "source": [
    "# Quantization of Image Classification Models\n",
    "\n",
    "This tutorial demonstrates how to apply `INT8` quantization to Image Classification model using [NNCF](https://github.com/openvinotoolkit/nncf). It uses the MobileNet V2 model, trained on Cifar10 dataset. The code is designed to be extendable to custom models and datasets. The tutorial uses OpenVINO backend for performing model quantization in NNCF, if you interested how to apply quantization on PyTorch model, please check this [tutorial](../pytorch-post-training-quantization-nncf/pytorch-post-training-quantization-nncf.ipynb).\n",
    "\n",
    "This tutorial consists of the following steps:\n",
    "\n",
    "- Prepare the model for quantization.\n",
    "- Define a data loading functionality.\n",
    "- Perform quantization.\n",
    "- Compare accuracy of the original and quantized models.\n",
    "- Compare performance of the original and quantized models.\n",
    "- Compare results on one picture.\n",
    "\n",
    "\n",
    "<img referrerpolicy=\"no-referrer-when-downgrade\" src=\"https://static.scarf.sh/a.png?x-pxid=5b5a4db0-7875-4bfb-bdbd-01698b5b1a77&file=notebooks/image-classification-quantization/image-classification-quantization.ipynb\" />\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "#### Table of contents:\n",
    "\n",
    "- [Prepare the Model](#Prepare-the-Model)\n",
    "- [Prepare Dataset](#Prepare-Dataset)\n",
    "- [Perform Quantization](#Perform-Quantization)\n",
    "    - [Create Dataset for Validation](#Create-Dataset-for-Validation)\n",
    "- [Run nncf.quantize for Getting an Optimized Model](#Run-nncf.quantize-for-Getting-an-Optimized-Model)\n",
    "- [Serialize an OpenVINO IR model](#Serialize-an-OpenVINO-IR-model)\n",
    "- [Compare Accuracy of the Original and Quantized Models](#Compare-Accuracy-of-the-Original-and-Quantized-Models)\n",
    "    - [Select inference device](#Select-inference-device)\n",
    "- [Compare Performance of the Original and Quantized Models](#Compare-Performance-of-the-Original-and-Quantized-Models)\n",
    "- [Compare results on four pictures](#Compare-results-on-four-pictures)\n",
    "\n",
    "\n",
    "### Installation Instructions\n",
    "\n",
    "This is a self-contained example that relies solely on its own code.\n",
    "\n",
    "We recommend  running the notebook in a virtual environment. You only need a Jupyter server to start.\n",
    "For details, please refer to [Installation Guide](https://github.com/openvinotoolkit/openvino_notebooks/blob/latest/README.md#-installation-guide)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install required packages\n",
    "%pip install -q \"openvino>=2023.1.0\" \"nncf>=2.6.0\" torch torchvision tqdm \"matplotlib>=3.4\" --extra-index-url https://download.pytorch.org/whl/cpu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "# Set the data and model directories\n",
    "DATA_DIR = Path(\"data\")\n",
    "MODEL_DIR = Path(\"model\")\n",
    "\n",
    "DATA_DIR.mkdir(exist_ok=True)\n",
    "MODEL_DIR.mkdir(exist_ok=True)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "D-frbVLKrkmv"
   },
   "source": [
    "## Prepare the Model\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "Model preparation stage has the following steps:\n",
    "\n",
    "- Download a PyTorch model\n",
    "- Convert model to OpenVINO Intermediate Representation format (IR) using model conversion Python API\n",
    "- Serialize converted model on disk\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "if not Path(\"notebook_utils.py\").exists():\n",
    "    r = requests.get(\n",
    "        url=\"https://raw.githubusercontent.com/openvinotoolkit/openvino_notebooks/latest/utils/notebook_utils.py\",\n",
    "    )\n",
    "    open(\"notebook_utils.py\", \"w\").write(r.text)\n",
    "\n",
    "if not Path(\"cmd_helper.py\").exists():\n",
    "    r = requests.get(\n",
    "        url=\"https://raw.githubusercontent.com/openvinotoolkit/openvino_notebooks/latest/utils/cmd_helper.py\",\n",
    "    )\n",
    "    open(\"cmd_helper.py\", \"w\").write(r.text)\n",
    "\n",
    "# Read more about telemetry collection at https://github.com/openvinotoolkit/openvino_notebooks?tab=readme-ov-file#-telemetry\n",
    "from notebook_utils import collect_telemetry\n",
    "\n",
    "collect_telemetry(\"image-classification-quantization.ipynb\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from cmd_helper import clone_repo\n",
    "\n",
    "\n",
    "clone_repo(\"https://github.com/chenyaofo/pytorch-cifar-models.git\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from pytorch_cifar_models import cifar10_mobilenetv2_x1_0\n",
    "\n",
    "model = cifar10_mobilenetv2_x1_0(pretrained=True)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "OpenVINO supports PyTorch models via conversion to OpenVINO Intermediate Representation format using model conversion Python API. `ov.convert_model` accept PyTorch model instance and convert it into `openvino.runtime.Model` representation of model in OpenVINO. Optionally, you may specify `example_input` which serves as a helper for model tracing and `input_shape` for converting the model with static shape. The converted model is ready to be loaded on a device for inference and can be saved on a disk for next usage via the `save_model` function. More details about model conversion Python API can be found on this [page](https://docs.openvino.ai/2024/openvino-workflow/model-preparation.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "f7i6dWUmhloy",
    "tags": []
   },
   "outputs": [],
   "source": [
    "import openvino as ov\n",
    "\n",
    "model.eval()\n",
    "\n",
    "ov_model = ov.convert_model(model, input=[1, 3, 32, 32])\n",
    "\n",
    "ov.save_model(ov_model, MODEL_DIR / \"mobilenet_v2.xml\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "ynLvh8rNc2wv"
   },
   "source": [
    "## Prepare Dataset\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "We will use [CIFAR10](https://www.cs.toronto.edu/~kriz/cifar.html) dataset from [torchvision](https://pytorch.org/vision/stable/generated/torchvision.datasets.CIFAR10.html). Preprocessing for model obtained from training [config](https://github.com/chenyaofo/image-classification-codebase/blob/master/conf/cifar10.conf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from torchvision import transforms\n",
    "from torchvision.datasets import CIFAR10\n",
    "\n",
    "transform = transforms.Compose(\n",
    "    [\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize((0.4914, 0.4822, 0.4465), (0.247, 0.243, 0.261)),\n",
    "    ]\n",
    ")\n",
    "dataset = CIFAR10(root=DATA_DIR, train=False, transform=transform, download=True)\n",
    "val_loader = torch.utils.data.DataLoader(\n",
    "    dataset,\n",
    "    batch_size=1,\n",
    "    shuffle=False,\n",
    "    num_workers=0,\n",
    "    pin_memory=True,\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Perform Quantization\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "[NNCF](https://github.com/openvinotoolkit/nncf) provides a suite of advanced algorithms for Neural Networks inference optimization in OpenVINO with minimal accuracy drop.\n",
    "We will use 8-bit quantization in post-training mode (without the fine-tuning pipeline) to optimize MobileNetV2.\n",
    "The optimization process contains the following steps:\n",
    "\n",
    "1. Create a Dataset for quantization.\n",
    "2. Run `nncf.quantize` for getting an optimized model.\n",
    "3. Serialize an OpenVINO IR model, using the `openvino.save_model` function.\n",
    "\n",
    "\n",
    "### Create Dataset for Validation\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "NNCF is compatible with `torch.utils.data.DataLoader` interface.  For performing quantization it should be passed into `nncf.Dataset` object with transformation function, which prepares input data to fit into model during quantization, in our case, to pick input tensor from pair (input tensor and label) and convert PyTorch tensor to numpy. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "id": "DErQofk8tO6c",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:nncf:NNCF initialized successfully. Supported frameworks detected: torch, tensorflow, onnx, openvino\n"
     ]
    }
   ],
   "source": [
    "import nncf\n",
    "\n",
    "\n",
    "def transform_fn(data_item):\n",
    "    image_tensor = data_item[0]\n",
    "    return image_tensor.numpy()\n",
    "\n",
    "\n",
    "quantization_dataset = nncf.Dataset(val_loader, transform_fn)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run nncf.quantize for Getting an Optimized Model\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "`nncf.quantize` function accepts model and prepared quantization dataset for performing basic quantization. Optionally, additional parameters like `subset_size`, `preset`, `ignored_scope` can be provided to improve quantization result if applicable. More details about supported parameters can be found on this [page](https://docs.openvino.ai/2024/openvino-workflow/model-optimization-guide/quantizing-models-post-training/basic-quantization-flow.html#tune-quantization-parameters)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": [],
    "test_replace": {
     "quant_ov_model = nncf.quantize(ov_model, quantization_dataset)": "quant_ov_model = nncf.quantize(ov_model, quantization_dataset, subset_size=10)"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Statistics collection: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 300/300 [00:06<00:00, 44.58it/s]\n",
      "Biases correction: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 36/36 [00:01<00:00, 24.92it/s]\n"
     ]
    }
   ],
   "source": [
    "quant_ov_model = nncf.quantize(ov_model, quantization_dataset)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Serialize an OpenVINO IR model\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "Similar to `ov.convert_model`, quantized model is `ov.Model` object which ready to be loaded into device and can be serialized on disk using `ov.save_model`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "ov.save_model(quant_ov_model, MODEL_DIR / \"quantized_mobilenet_v2.xml\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compare Accuracy of the Original and Quantized Models\n",
    "[back to top ⬆️](#Table-of-contents:)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from tqdm.notebook import tqdm\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "def test_accuracy(ov_model, data_loader):\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    for batch_imgs, batch_labels in tqdm(data_loader):\n",
    "        result = ov_model(batch_imgs)[0]\n",
    "        top_label = np.argmax(result)\n",
    "        correct += top_label == batch_labels.numpy()\n",
    "        total += 1\n",
    "    return correct / total"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Select inference device\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "select device from dropdown list for running inference using OpenVINO"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "source_hidden": true
    },
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ff9e95c4d1a9464f980a05ebca58fcbc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Dropdown(description='Device:', index=2, options=('CPU', 'GPU', 'AUTO'), value='AUTO')"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from notebook_utils import device_widget\n",
    "\n",
    "\n",
    "device = device_widget()\n",
    "\n",
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "6f318f01f707487495bf8464a8884098",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/10000 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b821f21f3d2345e3b598a02735be4173",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/10000 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "core = ov.Core()\n",
    "compiled_model = core.compile_model(ov_model, device.value)\n",
    "optimized_compiled_model = core.compile_model(quant_ov_model, device.value)\n",
    "\n",
    "orig_accuracy = test_accuracy(compiled_model, val_loader)\n",
    "optimized_accuracy = test_accuracy(optimized_compiled_model, val_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of the original model: 93.61%\n",
      "Accuracy of the optimized model: 93.51%\n"
     ]
    }
   ],
   "source": [
    "print(f\"Accuracy of the original model: {orig_accuracy[0] * 100 :.2f}%\")\n",
    "print(f\"Accuracy of the optimized model: {optimized_accuracy[0] * 100 :.2f}%\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {
    "id": "vQACMfAUo52V"
   },
   "source": [
    "## Compare Performance of the Original and Quantized Models\n",
    "[back to top ⬆️](#Table-of-contents:)\n",
    "\n",
    "Finally, measure the inference performance of the `FP32` and `INT8` models, using [Benchmark Tool](https://docs.openvino.ai/2024/learn-openvino/openvino-samples/benchmark-tool.html) - an inference performance measurement tool in OpenVINO.\n",
    "\n",
    "> **NOTE**: For more accurate performance, it is recommended to run benchmark_app in a terminal/command prompt after closing other applications. Run `benchmark_app -m model.xml -d CPU` to benchmark async inference on CPU for one minute. Change CPU to GPU to benchmark on GPU. Run `benchmark_app --help` to see an overview of all command-line options.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "id": "pC0gnO0c9-tI"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Step 1/11] Parsing and validating input arguments\n",
      "[ INFO ] Parsing input parameters\n",
      "[Step 2/11] Loading OpenVINO Runtime\n",
      "[ INFO ] OpenVINO:\n",
      "[ INFO ] Build ................................. 2023.0.0-10926-b4452d56304-releases/2023/0\n",
      "[ INFO ] \n",
      "[ INFO ] Device info:\n",
      "[ INFO ] AUTO\n",
      "[ INFO ] Build ................................. 2023.0.0-10926-b4452d56304-releases/2023/0\n",
      "[ INFO ] \n",
      "[ INFO ] \n",
      "[Step 3/11] Setting device configuration\n",
      "[ WARNING ] Performance hint was not explicitly specified in command line. Device(AUTO) performance hint will be set to PerformanceMode.THROUGHPUT.\n",
      "[Step 4/11] Reading model files\n",
      "[ INFO ] Loading model files\n",
      "[ INFO ] Read model took 8.60 ms\n",
      "[ INFO ] Original model I/O parameters:\n",
      "[ INFO ] Model inputs:\n",
      "[ INFO ]     x , 1 , x.1 (node: Parameter_2) : f32 / [...] / [1,3,32,32]\n",
      "[ INFO ] Model outputs:\n",
      "[ INFO ]     223 (node: aten::linear_928) : f32 / [...] / [1,10]\n",
      "[Step 5/11] Resizing model to match image sizes and given batch\n",
      "[ INFO ] Model batch size: 1\n",
      "[Step 6/11] Configuring input of the model\n",
      "[ INFO ] Model inputs:\n",
      "[ INFO ]     x , 1 , x.1 (node: Parameter_2) : u8 / [N,C,H,W] / [1,3,32,32]\n",
      "[ INFO ] Model outputs:\n",
      "[ INFO ]     223 (node: aten::linear_928) : f32 / [...] / [1,10]\n",
      "[Step 7/11] Loading the model to the device\n",
      "[ INFO ] Compile model took 312.76 ms\n",
      "[Step 8/11] Querying optimal runtime parameters\n",
      "[ INFO ] Model:\n",
      "[ INFO ]   PERFORMANCE_HINT: PerformanceMode.THROUGHPUT\n",
      "[ INFO ]   NETWORK_NAME: Model0\n",
      "[ INFO ]   OPTIMAL_NUMBER_OF_INFER_REQUESTS: 18\n",
      "[ INFO ]   MODEL_PRIORITY: Priority.MEDIUM\n",
      "[ INFO ]   MULTI_DEVICE_PRIORITIES: CPU\n",
      "[ INFO ]   CPU:\n",
      "[ INFO ]     CPU_BIND_THREAD: YES\n",
      "[ INFO ]     CPU_THREADS_NUM: 0\n",
      "[ INFO ]     CPU_THROUGHPUT_STREAMS: 18\n",
      "[ INFO ]     DEVICE_ID: \n",
      "[ INFO ]     DUMP_EXEC_GRAPH_AS_DOT: \n",
      "[ INFO ]     DYN_BATCH_ENABLED: NO\n",
      "[ INFO ]     DYN_BATCH_LIMIT: 0\n",
      "[ INFO ]     ENFORCE_BF16: NO\n",
      "[ INFO ]     EXCLUSIVE_ASYNC_REQUESTS: NO\n",
      "[ INFO ]     NETWORK_NAME: Model0\n",
      "[ INFO ]     OPTIMAL_NUMBER_OF_INFER_REQUESTS: 18\n",
      "[ INFO ]     PERFORMANCE_HINT: THROUGHPUT\n",
      "[ INFO ]     PERFORMANCE_HINT_NUM_REQUESTS: 0\n",
      "[ INFO ]     PERF_COUNT: NO\n",
      "[ INFO ]   EXECUTION_DEVICES: ['CPU']\n",
      "[Step 9/11] Creating infer requests and preparing input tensors\n",
      "[ WARNING ] No input files were given for input '1'!. This input will be filled with random values!\n",
      "[ INFO ] Fill input '1' with random values \n",
      "[Step 10/11] Measuring performance (Start inference asynchronously, 18 inference requests, limits: 15000 ms duration)\n",
      "[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).\n",
      "[ INFO ] First inference took 2.29 ms\n",
      "[Step 11/11] Dumping statistics report\n",
      "[ INFO ] Execution Devices:['CPU']\n",
      "[ INFO ] Count:            117540 iterations\n",
      "[ INFO ] Duration:         15005.85 ms\n",
      "[ INFO ] Latency:\n",
      "[ INFO ]    Median:        1.99 ms\n",
      "[ INFO ]    Average:       2.11 ms\n",
      "[ INFO ]    Min:           1.25 ms\n",
      "[ INFO ]    Max:           118.00 ms\n",
      "[ INFO ] Throughput:   7832.95 FPS\n"
     ]
    }
   ],
   "source": [
    "# Inference FP16 model (OpenVINO IR)\n",
    "!benchmark_app -m \"model/mobilenet_v2.xml\" -d $device.value -api async -t 15"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "id": "4VR3-joFu9hH"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Step 1/11] Parsing and validating input arguments\n",
      "[ INFO ] Parsing input parameters\n",
      "[Step 2/11] Loading OpenVINO Runtime\n",
      "[ INFO ] OpenVINO:\n",
      "[ INFO ] Build ................................. 2023.0.0-10926-b4452d56304-releases/2023/0\n",
      "[ INFO ] \n",
      "[ INFO ] Device info:\n",
      "[ INFO ] AUTO\n",
      "[ INFO ] Build ................................. 2023.0.0-10926-b4452d56304-releases/2023/0\n",
      "[ INFO ] \n",
      "[ INFO ] \n",
      "[Step 3/11] Setting device configuration\n",
      "[ WARNING ] Performance hint was not explicitly specified in command line. Device(AUTO) performance hint will be set to PerformanceMode.THROUGHPUT.\n",
      "[Step 4/11] Reading model files\n",
      "[ INFO ] Loading model files\n",
      "[ INFO ] Read model took 16.74 ms\n",
      "[ INFO ] Original model I/O parameters:\n",
      "[ INFO ] Model inputs:\n",
      "[ INFO ]     x , x.1 , 1 (node: Parameter_2) : f32 / [...] / [1,3,32,32]\n",
      "[ INFO ] Model outputs:\n",
      "[ INFO ]     223 (node: aten::linear_928) : f32 / [...] / [1,10]\n",
      "[Step 5/11] Resizing model to match image sizes and given batch\n",
      "[ INFO ] Model batch size: 1\n",
      "[Step 6/11] Configuring input of the model\n",
      "[ INFO ] Model inputs:\n",
      "[ INFO ]     x , x.1 , 1 (node: Parameter_2) : u8 / [N,C,H,W] / [1,3,32,32]\n",
      "[ INFO ] Model outputs:\n",
      "[ INFO ]     223 (node: aten::linear_928) : f32 / [...] / [1,10]\n",
      "[Step 7/11] Loading the model to the device\n",
      "[ INFO ] Compile model took 392.77 ms\n",
      "[Step 8/11] Querying optimal runtime parameters\n",
      "[ INFO ] Model:\n",
      "[ INFO ]   PERFORMANCE_HINT: PerformanceMode.THROUGHPUT\n",
      "[ INFO ]   NETWORK_NAME: Model0\n",
      "[ INFO ]   OPTIMAL_NUMBER_OF_INFER_REQUESTS: 18\n",
      "[ INFO ]   MODEL_PRIORITY: Priority.MEDIUM\n",
      "[ INFO ]   MULTI_DEVICE_PRIORITIES: CPU\n",
      "[ INFO ]   CPU:\n",
      "[ INFO ]     CPU_BIND_THREAD: YES\n",
      "[ INFO ]     CPU_THREADS_NUM: 0\n",
      "[ INFO ]     CPU_THROUGHPUT_STREAMS: 18\n",
      "[ INFO ]     DEVICE_ID: \n",
      "[ INFO ]     DUMP_EXEC_GRAPH_AS_DOT: \n",
      "[ INFO ]     DYN_BATCH_ENABLED: NO\n",
      "[ INFO ]     DYN_BATCH_LIMIT: 0\n",
      "[ INFO ]     ENFORCE_BF16: NO\n",
      "[ INFO ]     EXCLUSIVE_ASYNC_REQUESTS: NO\n",
      "[ INFO ]     NETWORK_NAME: Model0\n",
      "[ INFO ]     OPTIMAL_NUMBER_OF_INFER_REQUESTS: 18\n",
      "[ INFO ]     PERFORMANCE_HINT: THROUGHPUT\n",
      "[ INFO ]     PERFORMANCE_HINT_NUM_REQUESTS: 0\n",
      "[ INFO ]     PERF_COUNT: NO\n",
      "[ INFO ]   EXECUTION_DEVICES: ['CPU']\n",
      "[Step 9/11] Creating infer requests and preparing input tensors\n",
      "[ WARNING ] No input files were given for input '1'!. This input will be filled with random values!\n",
      "[ INFO ] Fill input '1' with random values \n",
      "[Step 10/11] Measuring performance (Start inference asynchronously, 18 inference requests, limits: 15000 ms duration)\n",
      "[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).\n",
      "[ INFO ] First inference took 2.20 ms\n",
      "[Step 11/11] Dumping statistics report\n",
      "[ INFO ] Execution Devices:['CPU']\n",
      "[ INFO ] Count:            210528 iterations\n",
      "[ INFO ] Duration:         15001.67 ms\n",
      "[ INFO ] Latency:\n",
      "[ INFO ]    Median:        1.04 ms\n",
      "[ INFO ]    Average:       1.10 ms\n",
      "[ INFO ]    Min:           0.71 ms\n",
      "[ INFO ]    Max:           79.19 ms\n",
      "[ INFO ] Throughput:   14033.63 FPS\n"
     ]
    }
   ],
   "source": [
    "# Inference INT8 model (OpenVINO IR)\n",
    "!benchmark_app -m \"model/quantized_mobilenet_v2.xml\" -d $device.value -api async -t 15"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compare results on four pictures\n",
    "[back to top ⬆️](#Table-of-contents:)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define all possible labels from the CIFAR10 dataset\n",
    "labels_names = [\n",
    "    \"airplane\",\n",
    "    \"automobile\",\n",
    "    \"bird\",\n",
    "    \"cat\",\n",
    "    \"deer\",\n",
    "    \"dog\",\n",
    "    \"frog\",\n",
    "    \"horse\",\n",
    "    \"ship\",\n",
    "    \"truck\",\n",
    "]\n",
    "all_pictures = []\n",
    "all_labels = []\n",
    "\n",
    "# Get all pictures and their labels.\n",
    "for i, batch in enumerate(val_loader):\n",
    "    all_pictures.append(batch[0].numpy())\n",
    "    all_labels.append(batch[1].item())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def plot_pictures(indexes: list, all_pictures=all_pictures, all_labels=all_labels):\n",
    "    \"\"\"Plot 4 pictures.\n",
    "    :param indexes: a list of indexes of pictures to be displayed.\n",
    "    :param all_batches: batches with pictures.\n",
    "    \"\"\"\n",
    "    images, labels = [], []\n",
    "    num_pics = len(indexes)\n",
    "    assert num_pics == 4, f\"No enough indexes for pictures to be displayed, got {num_pics}\"\n",
    "    for idx in indexes:\n",
    "        assert idx < 10000, \"Cannot get such index, there are only 10000\"\n",
    "        pic = np.rollaxis(all_pictures[idx].squeeze(), 0, 3)\n",
    "        images.append(pic)\n",
    "\n",
    "        labels.append(labels_names[all_labels[idx]])\n",
    "\n",
    "    f, axarr = plt.subplots(1, 4)\n",
    "    axarr[0].imshow(images[0])\n",
    "    axarr[0].set_title(labels[0])\n",
    "\n",
    "    axarr[1].imshow(images[1])\n",
    "    axarr[1].set_title(labels[1])\n",
    "\n",
    "    axarr[2].imshow(images[2])\n",
    "    axarr[2].set_title(labels[2])\n",
    "\n",
    "    axarr[3].imshow(images[3])\n",
    "    axarr[3].set_title(labels[3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def infer_on_pictures(model, indexes: list, all_pictures=all_pictures):\n",
    "    \"\"\"Inference model on a few pictures.\n",
    "    :param net: model on which do inference\n",
    "    :param indexes: list of indexes\n",
    "    \"\"\"\n",
    "    output_key = model.output(0)\n",
    "    predicted_labels = []\n",
    "    for idx in indexes:\n",
    "        assert idx < 10000, \"Cannot get such index, there are only 10000\"\n",
    "        result = model(all_pictures[idx])[output_key]\n",
    "        result = labels_names[np.argmax(result[0])]\n",
    "        predicted_labels.append(result)\n",
    "    return predicted_labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "test_replace": {
     "print(f\"Labels for picture from quantized model : {results_quanized}.\")": "print(f\"Labels for picture from quantized model : {results_quanized}.\")\n%pip uninstall -q -y torchvision\n"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n",
      "Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n",
      "Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n",
      "Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Labels for picture from float model : ['frog', 'dog', 'ship', 'horse'].\n",
      "Labels for picture from quantized model : ['frog', 'dog', 'ship', 'horse'].\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAACtCAYAAAAQwB2GAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA5dElEQVR4nO2deVxU5f7HPwMDMyDLoCiIIKKpuWVp7qm5m5ZZmta1rna1NMHyarfSFnG7li3aVdtLrSy1Mu1mmqb+XMqu5pYLIhoZLpAYw6IgDPP8/kDOs8DggDNnBvy+Xy9ffs95vnPOc858z5mH57s8BsYYA0EQBEEQhE74eLoDBEEQBEHcWNDggyAIgiAIXaHBB0EQBEEQukKDD4IgCIIgdIUGHwRBEARB6AoNPgiCIAiC0BUafBAEQRAEoSs0+CAIgiAIQldo8EEQBEEQhK7Q4KMK7N27F127dkWtWrVgMBhw8OBBT3eJ8CISExNhMBg83Q3Cw9x5551o3br1NfV+//13GAwGLFu2zP2dIqpE6TOdmZnp6a7UGIye7kB1o6ioCA888ADMZjMWLFiAwMBAxMbGerpbBEEQBFFtoMFHJTl16hROnz6N999/H+PGjfN0dwiCqObExsYiPz8ffn5+nu4KQegGuV0qyZ9//gkAsFgsFepdunRJh94QBFHdMRgMMJvN8PX19XRXCA/BGEN+fr6nu6ErNPioBGPGjEHPnj0BAA888AAMBgPuvPNOjBkzBkFBQTh16hQGDRqE4OBgjBo1CkDJIGTq1KmIiYmByWRC8+bN8dprr0FdTDg/Px9PPvkkwsPDERwcjCFDhuDs2bMwGAxITEzU+1IJJ9m1axc6dOgAs9mMJk2a4N133y2jY7PZMHv2bDRp0gQmkwmNGjXC9OnTceXKFUnPbrcjMTERUVFRCAwMRK9evXDs2DE0atQIY8aM0emKCGfJzc3F5MmT0ahRI5hMJtSrVw/9+vXD/v37Jb1jx46hV69eCAwMRIMGDTB//nypvbyYj9J3ym+//YYBAwagVq1aiIqKwqxZs8q8Owj9sFqtGDNmDCwWC0JDQ/Hoo4/i8uXLWruzz3qjRo1w99134/vvv8ftt9+OgIAA7d2xefNm3HHHHbBYLAgKCkLz5s0xffp06fNXrlzBjBkzcNNNN8FkMiEmJgbPPPNMmfN4M+R2qQTjx49HgwYN8O9//xtPPvkkOnTogIiICKxYsQI2mw0DBgzAHXfcgddeew2BgYFgjGHIkCHYtm0bxo4di1tvvRXff/89/vWvf+Hs2bNYsGCBduwxY8Zg9erVeOSRR9C5c2ds374dgwcP9uDVEtfi8OHD6N+/P+rWrYvExETYbDbMmDEDERERkt64ceOwfPlyDB8+HFOnTsX//vc/zJs3D0lJSfj66681vWnTpmH+/Pm45557MGDAABw6dAgDBgxAQUGB3pdGOMGECRPw5ZdfIiEhAS1btsTFixexa9cuJCUloV27dgCArKwsDBw4EPfffz9GjBiBL7/8Es8++yzatGmDu+66q8LjFxcXY+DAgejcuTPmz5+PjRs3YsaMGbDZbJg1a5Yel0gojBgxAnFxcZg3bx7279+PDz74APXq1cMrr7wCwPlnHQCSk5Px0EMPYfz48XjsscfQvHlzHD16FHfffTduueUWzJo1CyaTCSdPnsSPP/6ofc5ut2PIkCHYtWsXHn/8cbRo0QKHDx/GggULcOLECaxdu1bPW1J1GFEptm3bxgCwL774Qts3evRoBoA999xzku7atWsZADZnzhxp//Dhw5nBYGAnT55kjDG2b98+BoBNnjxZ0hszZgwDwGbMmOGeiyGui6FDhzKz2cxOnz6t7Tt27Bjz9fVlpY/WwYMHGQA2btw46bNPP/00A8C2bt3KGGMsPT2dGY1GNnToUEkvMTGRAWCjR49278UQlSY0NJTFx8c7bO/ZsycDwD7++GNt35UrV1hkZCQbNmyYti81NZUBYEuXLtX2lb5TJk2apO2z2+1s8ODBzN/fn124cMG1F0NUyIwZMxgA9o9//EPaf99997E6deowxpx/1hljLDY2lgFgGzdulHQXLFjAAFT4/X7yySfMx8eH7dy5U9r/zjvvMADsxx9/rNI16g25XVzIE088IW1/99138PX1xZNPPintnzp1Khhj2LBhAwBg48aNAICJEydKepMmTXJjb4nrobi4GN9//z2GDh2Khg0bavtbtGiBAQMGaNvfffcdAGDKlCnS56dOnQoAWL9+PQBgy5YtsNlsZAPVCIvFgv/97384d+6cQ52goCA8/PDD2ra/vz86duyI3377zalzJCQkaLLBYEBCQgIKCwvxww8/VL3jRJWZMGGCtN29e3dcvHgROTk5Tj/rpcTFxUnvCoDHEq5btw52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",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "indexes_to_infer = [7, 12, 15, 20]  # To plot, specify 4 indexes.\n",
    "\n",
    "plot_pictures(indexes_to_infer)\n",
    "\n",
    "results_float = infer_on_pictures(compiled_model, indexes_to_infer)\n",
    "results_quanized = infer_on_pictures(optimized_compiled_model, indexes_to_infer)\n",
    "\n",
    "print(f\"Labels for picture from float model : {results_float}.\")\n",
    "print(f\"Labels for picture from quantized model : {results_quanized}.\")"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "tutorial_tiny.ipynb",
   "private_outputs": true,
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  },
  "openvino_notebooks": {
   "imageUrl": "",
   "tags": {
    "categories": [
     "Optimize",
     "API Overview"
    ],
    "libraries": [],
    "other": [],
    "tasks": [
     "Image Classification"
    ]
   }
  },
  "vscode": {
   "interpreter": {
    "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
   }
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
